from openpyxl import load_workbook, Workbook
from sinotrans.core.rule import Rule
from typing import get_type_hints
import os

class FileParser:
    """
    文件处理类,解析映射规则，创建输出文件,返回：
    {
    "src_field_name1":[rule1, rule2, ...],
    "src_field_name2":[rule1, rule2, ...],
    ...
    }
    """
    @staticmethod
    def ensure_directories_exist(directories):
        """
        确保所有必要的目录存在，如果不存在则创建它们
        """
        for directory in directories:
            if not os.path.exists(directory):
                os.makedirs(directory)
    @staticmethod
    def create_newfile_by_template(template_file_name, target_file_name, column_names = None):
            """
            创建新文件，并复制模板表头
            可选：添加新列
            """
            # 加载模板并获取表头（第一行数据）
            header_row = next(load_workbook(template_file_name).active.iter_rows(max_row=1, values_only=True))  # 提取第一行数据
            # 添加新列
            header_row = list(header_row)
            if not column_names:
                header_row.extend(column_names)
            # 创建新工作簿并写入表头
            new_wb = Workbook()
            new_sheet = new_wb.active
            new_sheet.append(header_row)
            
            new_wb.save(target_file_name)
            return new_wb
    @staticmethod
    def parse_rule(value, prefix_separator, condition_separator, key_value_separator):
        """
        解析"指定单行"中"指定格式分隔符"的键值对格式的字符串，将其解析成：
        Rule对象
        """
        # 初始化Rule对象
        rule = Rule(field_name=value.split('|')[0].strip())
        # 获取Rule对象的属性类型
        type_hints = get_type_hints(type(rule))
        # 解析参数键值对
        if prefix_separator in value:
            # 先取条件字符串
            params_str = value.split(prefix_separator, 1)[1]
            # 遍历条件
            for param in params_str.split(condition_separator):
                # param不要去掉末尾空格，不然分隔符为空格的时候就会被误删！
                param = param
                if key_value_separator not in param:
                    continue
                # 分割当前条件，提取键值对
                k, v = param.split(key_value_separator, 1)
                k = k.strip().lower()
                # 判断属性是否存在，存在则尝试转换类型并赋值
                if hasattr(rule, k):
                    attr_type = type_hints[k]
                    try:
                        converted_v = attr_type(v)
                        setattr(rule, k, converted_v)
                    except (TypeError, ValueError) as e:
                        raise ValueError(f"❌ 参数 {k} 的值 {v} 无法转换为正确类型: {e}")
        return rule
    @staticmethod
    def parse_mapping_dict(file_name, splitter, prefix_separator, condition_separator, key_value_separator):
        """
        解析"指定文件"中"指定格式分隔符"的键值对格式的所有行，将其解析成：
        {
        "src_field_name1":rule1,
        "src_field_name2":rule2,
        ...
        }
        """
        mapping = {}
        with open(file_name, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if not line or splitter not in line:
                    continue
                key, value = line.split(splitter, 1)
                rule = FileParser.parse_rule(value, prefix_separator, condition_separator, key_value_separator)
                mapping[key.strip()] = rule
        return mapping
    @staticmethod
    def parse_mapping_dict_of_list(file_name, splitter, prefix_separator, condition_separator, key_value_separator):
        """
        解析"指定文件"中"指定格式分隔符"的键值对格式的所有行，将其解析成：
        {
        "src_field_name1":[rule1, rule2, ...],
        "src_field_name2":[rule1, rule2, ...],
        ...
        }
        """
        mapping = {}
        with open(file_name, 'r', encoding='utf-8') as f:
            for line in f:
                # 去除空白字符
                line = line.strip()
                # 根据splitter分隔符判断该行是否有效——键值对格式，否则，跳过
                if not line or splitter not in line:
                    continue
                # 根据splitter分隔符，获取键值对
                key, value = line.split(splitter, 1)
                # 映射对象存在，则追加rule, 否则，新建
                if key not in mapping:
                    mapping[key] = []
                rule = FileParser.parse_rule(value, prefix_separator, condition_separator, key_value_separator)
                mapping[key.strip()].append(rule)
        return mapping